#ifndef quantlib_single_floating_leg_hpp
#define quantlib_single_floating_leg_hpp

#include <ql/instruments/swap.hpp>
#include <ql/time/daycounter.hpp>
#include <ql/time/schedule.hpp>
#include <boost/optional.hpp>

namespace QuantLib {

    class IborIndex;

    class SingleFloatingLeg : public Swap {
      public:
        enum Type { Receiver = -1, Payer = 1 };
        class arguments;
        class results;
        class engine;
        SingleFloatingLeg(
            Type type,
            Real nominal,
            const Schedule& floatingSchedule,
            const boost::shared_ptr<IborIndex>& iborIndex,
			Spread spread,
            const DayCounter& floatingDayCount);

        Type type() const;
        Real nominal() const;


        const Schedule& floatingSchedule() const;
		const boost::shared_ptr<IborIndex>& iborIndex() const;
		Spread spread() const;
        const DayCounter& floatingDayCount() const;
		BusinessDayConvention paymentConvention() const;

        const Leg& floatingLeg() const;
        //@}

        //! \name Results
        //@{
        Real floatingLegBPS() const;
        Real floatingLegNPV() const;
        Rate fairSpread() const;

        //@}
        // other
        void setupArguments(PricingEngine::arguments* args) const;
        void fetchResults(const PricingEngine::results*) const;
      private:
        void setupExpired() const;
        Type type_;
        Real nominal_;
        
		Schedule floatingSchedule_;
        boost::shared_ptr<IborIndex> iborIndex_;
		Spread spread_;
        DayCounter floatingDayCount_;

		BusinessDayConvention paymentConvention_;

        // results
        mutable Spread fairSpread_;
    };


    //! %Arguments for simple swap calculation
    class SingleFloatingLeg::arguments : public Swap::arguments {
      public:
        arguments() : type(Receiver),
                      nominal(Null<Real>()) {}
        Type type;
        Real nominal;

		std::vector<Time> floatingAccrualTimes;
        std::vector<Date> floatingResetDates;
        std::vector<Date> floatingFixingDates;
        std::vector<Date> floatingPayDates;
		std::vector<Spread> floatingSpreads;
		std::vector<Real> floatingCoupons;

       
		void validate() const;
    };

    //! %Results from simple swap calculation
    class SingleFloatingLeg::results : public Swap::results {
      public:
        Spread fairSpread;
        void reset();
    };

    class SingleFloatingLeg::engine : public GenericEngine<SingleFloatingLeg::arguments,
                                                     SingleFloatingLeg::results> {};


    // inline definitions

    inline SingleFloatingLeg::Type SingleFloatingLeg::type() const {
        return type_;
    }

    inline Real SingleFloatingLeg::nominal() const {
        return nominal_;
    }
	
    inline BusinessDayConvention SingleFloatingLeg::paymentConvention() const {
        return paymentConvention_;
    }

    inline const Schedule& SingleFloatingLeg::floatingSchedule() const {
        return floatingSchedule_;
    }

	inline const boost::shared_ptr<IborIndex>& SingleFloatingLeg::iborIndex() const {
        return iborIndex_;
    }

	inline const DayCounter& SingleFloatingLeg::floatingDayCount() const {
        return floatingDayCount_;
    }

	inline Spread SingleFloatingLeg::spread() const {
        return spread_;
    }


    inline const Leg& SingleFloatingLeg::floatingLeg() const {
        return legs_[0];
    }

    std::ostream& operator<<(std::ostream& out, SingleFloatingLeg::Type t);

}

#endif
